package com.ll.blog.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ll.blog.Exception.BlogException;
import com.ll.blog.annotation.Record;
import com.ll.blog.common.ApiResponse;
import com.ll.blog.contant.ArticleStatusEnum;
import com.ll.blog.contant.BehaviorEnum;
import com.ll.blog.contant.ExceptionEnum;
import com.ll.blog.contant.OrderEnum;
import com.ll.blog.entity.Article;
import com.ll.blog.entity.Relevancy;
import com.ll.blog.entity.Tag;
import com.ll.blog.model.query.ArticleQuery;
import com.ll.blog.model.query.ArticleTagQuery;
import com.ll.blog.model.res.ArticleDetailRes;
import com.ll.blog.model.res.PageDto;
import com.ll.blog.service.IArticleService;
import com.ll.blog.service.IRelevancyService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.List;


/**
 * 文章模块
 */
@RestController
@Validated
public class ArticleController {
    @Autowired
    private IArticleService articleService;
    @Resource
    IRelevancyService relevancyService;

    /**
     * 分页获取文章
     */
    @GetMapping("/article")
    public ApiResponse articleList(ArticleQuery query) {
        PageDto<ArticleDetailRes> dto = articleService.getArticlebypage(query);
        return ApiResponse.success(dto);
    }

    /**
     * 文章详情
     *
     * @param id 文章id
     */
    @Record(type = BehaviorEnum.ARTICLE_MODULE)
    @GetMapping("/article/{id}")
    public ApiResponse articleDetail(@PathVariable Integer id) {
        Article article = articleService.getById(id);
        List<Tag> list = relevancyService.getTagList(id);
        if (article == null) {
            return ApiResponse.error(ExceptionEnum.ARTICLE_NOT_FOUND);
        }
        ArticleDetailRes detailReq = new ArticleDetailRes();
        BeanUtils.copyProperties(article, detailReq);
        detailReq.setTags(list);
        return ApiResponse.success(detailReq);
    }

    /**
     * 分页按照标签获取文章
     */
    @GetMapping("article/tag")
    public ApiResponse articleByTag(ArticleTagQuery query) {
        PageDto<Article> page = articleService.getArticleByTagtoPage(query);
        return ApiResponse.success(page);

    }

    /**
     * 文章添加
     */
    @Transactional
    @PostMapping("admin/article/add")
    public ApiResponse add(@RequestBody ArticleQuery.addArticleReq req) {
        Article article = new Article();
        BeanUtils.copyProperties(req, article);
        ArticleStatusEnum statusEnum = ArticleStatusEnum.codeToEnum(req.getStatus());
        if (statusEnum==null){
            throw new BlogException(ExceptionEnum.PARAMS_ERROR);
        }
        article.setStatus(statusEnum);
        boolean saved = articleService.save(article);
        if (!saved) {
            throw new RuntimeException();
//            return ApiResponse.error(ExceptionEnum.SAVE_ERROR);
        }
        Integer id = article.getId();
        List<Integer> tags = req.getTags();
        if (tags!=null&& !tags.isEmpty()) {
            for (Integer tag : tags) {
                Relevancy relevancy = new Relevancy();
                relevancy.setArticleId(id);
                relevancy.setTagId(tag);
                boolean save = relevancyService.save(relevancy);
                if (!save) {
                    throw new RuntimeException();
                }
            }
        }
        return ApiResponse.success();
    }

    /**
     * 更新文章
     *
     * @param id 文章id
     */
    @Transactional
    @PutMapping("/admin/article/update/{id}")
    public ApiResponse update(@PathVariable Integer id, @RequestBody ArticleQuery.updateArticleReq req) {
        Article article = new Article();
        BeanUtils.copyProperties(req, article);
        if (req.getStatus()!=null){
            ArticleStatusEnum statusEnum = ArticleStatusEnum.codeToEnum(req.getStatus());
            if (statusEnum==null){
                throw new BlogException(ExceptionEnum.PARAMS_ERROR);
            }
            article.setStatus(statusEnum);
        }
        if (req.getIsTop()!=null){
            OrderEnum order = OrderEnum.getEnumByCode(req.getIsTop());
            if (order == null) {
                throw new BlogException(ExceptionEnum.PARAMS_ERROR);
            }
            article.setIsTop(order);
        }
        List<Integer> tags = req.getTags();
        if (tags != null) {
            LambdaQueryWrapper<Relevancy> wrapper = new QueryWrapper<Relevancy>().lambda();
            wrapper.eq(Relevancy::getArticleId, id);
            boolean remove = relevancyService.remove(wrapper);
            if (!tags.isEmpty()) {
                for (Integer tag : tags) {
                    Relevancy relevancy = new Relevancy();
                    relevancy.setArticleId(id);
                    relevancy.setTagId(tag);
                    boolean saved = relevancyService.save(relevancy);
                    if (!saved) {
                        throw new RuntimeException();
                    }
                }
            }
        }
        if (checkNull(article)){
            article.setId(id);
            boolean b = articleService.updateById(article);
            if (!b) {
                throw new RuntimeException();
            }
        }
        return ApiResponse.success();
    }


    private Boolean checkNull(Article article){

        Field[] fields = article.getClass().getDeclaredFields();

        try {
            for (Field field : fields) {
                field.setAccessible(true);
                if (field.get(article) != null && !field.getName().equals("serialVersionUID")) {
                    return true;
                }
            }
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    /**
     * 删除文章
     *
     * @param id 文章id
     */
    @DeleteMapping("/admin/article/delete/{id}")
    public ApiResponse delete(@PathVariable Integer id) {
        Article article = new Article();
        article.setId(id);
        boolean b = articleService.removeById(article);
        if (!b) {
            return ApiResponse.error(ExceptionEnum.DELETE_ERROR);
        }
        return ApiResponse.success();
    }


}
